package com.lili.collection.core.runner.pipe;

import com.lili.collection.core.event.StageEventListener;
import com.lili.collection.core.runner.PipeRunner;
import com.lili.collection.core.runner.StageGroupRunner;
import com.lili.collection.core.runner.StageRunner;
import com.lili.collection.core.runner.group.GenericProcessorGroupRunner;
import com.lili.collection.core.runner.stage.GenericInputRunner;
import com.lili.collection.core.runner.stage.GenericOutputRunner;
import com.lili.collection.core.support.Disposable;
import com.lili.collection.core.support.PreHandleSupport;
import lombok.Getter;

import java.util.LinkedList;
import java.util.List;

/**
 * AbstractPipeRunner
 *
 * @author lili
 * @date 2023/3/8 0:58
 */
public abstract class AbstractPipeRunner implements PipeRunner, StageEventListener {

    @Getter
    private StageRunner inputRunner;

    @Getter
    private StageRunner outputRunner;

    private StageGroupRunner processorGroupRunner;

    protected List<StageRunner> stageRunnerList = new LinkedList<>();


    protected void ensureStageRunner() {
        resolveInputRunner();
        resolveProcessorGroupRunner();
        resolveOutputRunner();
    }

    private void resolveInputRunner() {
        if (this.inputRunner == null) {
            this.inputRunner = this.getStageInputRunner();
            this.inputRunner.registerStageEventListener(this);
            this.stageRunnerList.add(this.inputRunner);
        }
    }

    public StageRunner getStageInputRunner(){
        return new GenericInputRunner(getPipeContext());
    }

    private void resolveOutputRunner() {
        if (this.outputRunner == null) {
            this.outputRunner = this.getStageOutputRunner();
            this.outputRunner.registerStageEventListener(this);
            this.stageRunnerList.add(this.outputRunner);
        }
    }

    public StageRunner getStageOutputRunner(){
        return new GenericOutputRunner(getPipeContext());
    }

    private void resolveProcessorGroupRunner() {
        if (this.processorGroupRunner == null) {
            this.processorGroupRunner = this.getStageProcessorGroupRunner();
            this.processorGroupRunner.registerStageEventListener(this);
            this.stageRunnerList.add(this.processorGroupRunner);
        }
    }

    public StageGroupRunner getStageProcessorGroupRunner(){
        return new GenericProcessorGroupRunner(getPipeContext());
    }

    @Override
    public void pause() {
    }

    @Override
    public void resume() {
    }

    @Override
    public void stop() {
    }

    @Override
    public void dispose() {
        dispose(inputRunner);
        dispose(processorGroupRunner);
        dispose(outputRunner);
        if (this.getPipeContext() != null && this.getPipeContext().getExchangeStageContext() != null)
            this.getPipeContext().getExchangeStageContext().clear();
    }

    private void dispose(Disposable disposable) {
        if (disposable != null) disposable.dispose();
    }

    public void execPreHandle() {
        for (StageRunner stageRunner : this.stageRunnerList) {
            if(stageRunner instanceof PreHandleSupport){
                stageRunner.preHandle();
            }
        }
    }
}
